import type { RouteRecordName, RouteRecordRaw } from 'vue-router'
import { asyncRoutes as _asyncRoutes_, systemRoutes } from '@g/router/routes'
import { _, ikStore, ikTree } from 'iking-utils'
import { resolveRoutePath } from '@g/utils'
import type { Route } from '@g/types/global'
import { ElMessage } from 'element-plus'
import menuApi from '@main/apis/menu'
import { userApi } from '@main/apis/user'
import router from '@g/router'
import useSettingsStore from './settings'
import useUserStore from './user'
import useTabbarStore from './tabbar'
import { MenuBtnEnum, MenuJumpEnum, MenuStorageEnum } from '@/global/enums/menu'
const Layout = () => import('@main/layouts/index.vue')

const useRouteStore = defineStore(
  // 唯一ID
  'route',
  () => {
    const settingsStore = useSettingsStore()
    const userStore = useUserStore()
    const tabbarStore = useTabbarStore()

    const isGenerate = ref(false)
    const routes = ref<Route.recordMainRaw[]>([])
    const routesUnallowed = ref<Route.recordMainRaw[]>([])
    const fileSystemRoutes = ref<RouteRecordRaw[]>([])
    const currentRemoveRoutes = ref<Function[]>([])
    const systemMenuTree = ref<RouteRecordRaw[]>([])
    const systemMenuList = ref<RouteRecordRaw[]>([])
    const systemRouteMenu = ref<RouteRecordRaw[]>([])

    // 将多层嵌套路由处理成两层，保留顶层和最子层路由，中间层级将被拍平
    function flatAsyncRoutes<T extends RouteRecordRaw>(_routes: T): T {
      if (_routes.children) {
        _routes.children = flatAsyncRoutesRecursive(_routes.children, [{
          path: _routes.path,
          title: _routes.meta?.title,
          i18n: _routes.meta?.i18n,
          icon: _routes.meta?.icon,
          activeIcon: _routes.meta?.activeIcon,
          hide: !_routes.meta?.breadcrumb && _routes.meta?.breadcrumb === false
        }], _routes.path)
      }
      return _routes
    }
    function flatAsyncRoutesRecursive(_routes: RouteRecordRaw[], breadcrumb: Route.breadcrumb[] = [], baseUrl = ''): RouteRecordRaw[] {
      const res: RouteRecordRaw[] = []
      _routes.forEach(route => {
        if (route.children) {
          const childrenBaseUrl = resolveRoutePath(baseUrl, route.path)
          const tmpBreadcrumb = _.cloneDeep(breadcrumb)
          tmpBreadcrumb.push({
            path: childrenBaseUrl,
            title: route.meta?.title,
            i18n: route.meta?.i18n,
            icon: route.meta?.icon,
            activeIcon: route.meta?.activeIcon,
            hide: !route.meta?.breadcrumb && route.meta?.breadcrumb === false
          })
          const tmpRoute = _.cloneDeep(route)
          tmpRoute.path = childrenBaseUrl
          if (!tmpRoute.meta)
            tmpRoute.meta = {}

          tmpRoute.meta.breadcrumbNeste = tmpBreadcrumb
          delete tmpRoute.children
          res.push(tmpRoute)
          const childrenRoutes = flatAsyncRoutesRecursive(route.children, tmpBreadcrumb, childrenBaseUrl)
          childrenRoutes.forEach(item => {
            // 如果 path 一样则覆盖，因为子路由的 path 可能设置为空，导致和父路由一样，直接注册会提示路由重复
            if (res.some(v => v.path === item.path)) {
              res.forEach((v, i) => {
                if (v.path === item.path)
                  res[i] = item
              })
            }
            else {
              res.push(item)
            }
          })
        }
        else {
          const tmpRoute = _.cloneDeep(route)
          tmpRoute.path = resolveRoutePath(baseUrl, tmpRoute.path)
          // 处理面包屑导航
          const tmpBreadcrumb = _.cloneDeep(breadcrumb)
          tmpBreadcrumb.push({
            path: tmpRoute.path,
            title: tmpRoute.meta?.title,
            i18n: tmpRoute.meta?.i18n,
            icon: tmpRoute.meta?.icon,
            activeIcon: tmpRoute.meta?.activeIcon,
            hide: !tmpRoute.meta?.breadcrumb && tmpRoute.meta?.breadcrumb === false
          })
          if (!tmpRoute.meta)
            tmpRoute.meta = {}

          tmpRoute.meta.breadcrumbNeste = tmpBreadcrumb
          res.push(tmpRoute)
        }
      })
      return res
    }
    // 扁平化路由（将三级及以上路由数据拍平成二级）
    const flatRoutes = computed(() => {
      const returnRoutes: RouteRecordRaw[] = []
      if (settingsStore.settings.app.routeBaseOn !== 'filesystem') {
        if (routes.value) {
          routes.value.forEach(item => {
            returnRoutes.push(..._.cloneDeep(item.children) as RouteRecordRaw[])
          })
          returnRoutes.forEach(item => flatAsyncRoutes(item))
        }
      }
      else {
        returnRoutes.push(..._.cloneDeep(fileSystemRoutes.value) as RouteRecordRaw[])
      }
      return returnRoutes
    })
    const flatRoutesUnallowed = computed(() => {
      const twoLevelRoutes: RouteRecordRaw[] = []
      if (settingsStore.settings.app.routeBaseOn !== 'filesystem') {
        if (routesUnallowed.value) {
          routesUnallowed.value.forEach(item => {
            twoLevelRoutes.push(..._.cloneDeep(item.children) as RouteRecordRaw[])
          })
          twoLevelRoutes.forEach(item => flatAsyncRoutes(item))
        }
      }
      else {
        twoLevelRoutes.push(..._.cloneDeep(routesUnallowed.value) as RouteRecordRaw[])
      }
      const returnRoutes: RouteRecordRaw[] = []
      twoLevelRoutes.forEach(item => {
        if (item.children) {
          item.children.forEach(child => {
            const tmpChild = _.cloneDeep(child)
            tmpChild.path = resolveRoutePath(item.path, tmpChild.path)
            tmpChild.component = () => import('@main/403.vue')
            returnRoutes.push(tmpChild)
          })
        }
      })
      return returnRoutes
    })
    const flatSystemRoutes = computed(() => {
      const routes = [...systemRoutes]
      routes.forEach(item => flatAsyncRoutes(item))
      return routes
    })

    // 判断是否有权限
    function hasPermission(permissions: string[], route: Route.recordMainRaw | RouteRecordRaw) {
      let isAuth = false
      if (route.meta?.auth) {
        isAuth = permissions.some(auth => {
          if (typeof route.meta?.auth === 'string')
            return route.meta.auth !== '' ? route.meta.auth === auth : true

          else if (typeof route.meta?.auth === 'object')
            return route.meta.auth.length > 0 ? route.meta.auth.includes(auth) : true

          else
            return false
        })
      }
      else {
        isAuth = true
      }
      return isAuth
    }
    // 根据权限过滤路由
    function filterAsyncRoutes<T extends Route.recordMainRaw[] | RouteRecordRaw[]>(routes: T, permissions: string[]): T {
      const res: any = []
      routes.forEach(route => {
        if (hasPermission(permissions, route)) {
          const tmpRoute = _.cloneDeep(route)
          if (tmpRoute.children) {
            tmpRoute.children = filterAsyncRoutes(tmpRoute.children, permissions)
            tmpRoute.children.length && res.push(tmpRoute)
          }
          else {
            res.push(tmpRoute)
          }
        }
      })
      return res
    }
    // 根据权限过滤路由（过滤出没有权限的路由）
    function filterAsyncRoutesNoAuth<T extends Route.recordMainRaw[] | RouteRecordRaw[]>(routes: T, permissions: string[]): T {
      const res: any = []
      routes.forEach(route => {
        const tmpRoute = _.cloneDeep(route)
        if (hasPermission(permissions, route)) {
          if (tmpRoute.children) {
            tmpRoute.children = filterAsyncRoutesNoAuth(tmpRoute.children, permissions)
            tmpRoute.children.length && res.push(tmpRoute)
          }
        }
        else {
          res.push(tmpRoute)
        }
      })
      return res
    }
    // 根据权限动态生成路由（前端生成）
    async function generateRoutesAtFront(asyncRoutes: Route.recordMainRaw[]) {
      let allowedRoutes
      let unallowedRoutes: Route.recordMainRaw[] = []
      // 如果权限功能开启，则需要对路由数据进行筛选过滤
      if (settingsStore.settings.app.enablePermission) {
        const permissions = await userStore.getPermissions()
        allowedRoutes = filterAsyncRoutes(asyncRoutes, permissions)
        unallowedRoutes = filterAsyncRoutesNoAuth(asyncRoutes, permissions)
      }
      else {
        allowedRoutes = _.cloneDeep(asyncRoutes)
      }
      // 设置 routes 数据
      isGenerate.value = true
      routes.value = allowedRoutes.filter(item => item.children?.length !== 0) as any
      routesUnallowed.value = unallowedRoutes as any
      // 加载常驻标签页
      if (settingsStore.settings.tabbar.enable)
        tabbarStore.initPermanentTab()
    }

    const mainViews = import.meta.glob('@main/views/**/*.vue')
    const microViews = import.meta.glob('@micro/views/**/*.vue')
    // 格式化后端路由数据
    function formatBackRoutes(routes: any, views = mainViews): Route.recordMainRaw[] {
      return routes.map((route: any) => {
        switch (route.component) {
          case 'Layout':
            route.component = () => import('@main/layouts/index.vue')
            break
          default:
            if (route.component) {
              if (route.framework)
                // 系统框架下的路由
                route.component = mainViews[`/src/MainApp/views/${route.component}`]
              else
                // 业务系统路由
                route.component = microViews[`/src/MicroApp/views/${route.component}`]
            }
        }
        if (route.children)
          route.children = formatBackRoutes(route.children, views)

        return route
      })
    }
    // 根据权限动态生成路由（后端获取）
    async function generateRoutesAtBack() {
      ElMessage.info('加载菜单...')
      await menuApi.getUserMenuList(false).then(async res => {
        // 设置 routes 数据
        isGenerate.value = true
        const routesMenu = res.data.filter((v: { menuType: MenuBtnEnum; }) => v.menuType === MenuBtnEnum.MENU)
        const _routes = routesMenu.map((v: any) => {
          const linkStartWidth = v.link.startsWith('/')
          if (v.parentId && linkStartWidth)
            v.link = v.link.substring(1)
          const fPath = linkStartWidth ? v.link : v.parentId ? v.link : `/${v.link}`
          return {
            ...v,
            name: v.name,
            id: v.id,
            parentId: v.parentId,
            component: v.component,
            path: fPath,
            meta: {
              id: v.id,
              cache: v.keepAlive,
              title: v.name,
              i18n: '',
              icon: v.icon,
              isFirstLevel: !v.parentId,
              link: v.jumpType === MenuJumpEnum.EXTERNAL_LINK ? v.link : undefined,
              path: fPath,
              iframe: v.iframe,
              visible: v.visible,
              // 指定高亮侧边栏路由，需要设置完整路由地址
              activeMenu: v.activeMenu,
              // 该路由是否在侧边栏导航中展示
              sidebar: v.sidebar,
              // 该路由是否在面包屑导航中展示
              breadcrumb: v.breadcrumb,
              // 次导航是否默认展开
              defaultOpened: v.defaultOpened,
              activeIcon: v.activeIcon,
              badge: v.badge ? v.badge === 'point' ? true : v.badge : false // boolean | string | number
            }
          }
        })
        const routeTree = ikTree.listToTree(_routes)
        const asyncRoutes = formatBackRoutes(routeTree)
        asyncRoutes.forEach((rou: any) => {
          if (!rou.path.startsWith('/')) {
            rou.path = `/${rou.path}`
            rou.children = []
          }
        })
        // TODO
        const fixasyncRoutes = asyncRoutes.map(rou => {
          return rou?.children
            ? {
                meta: rou.meta,
                children: rou.children.map((ro: any) => {
                  return ro.children
                    ? {
                        ...ro,
                        path: `/${ro.path}`,
                        component: Layout,
                        children: [{
                          name: ro.name,
                          id: ro?.id,
                          parentId: ro?.parentId,
                          component: ro.component,
                          ...ro.meta,
                          path: ro.children ? '' : ro.path,
                          meta: {
                            ...ro.meta,
                            sidebar: false,
                            breadcrumb: false
                          }
                        }, ...ro.children]
                      }
                    : {
                        ...ro,
                        path: `/${ro.path}`,
                        component: Layout,
                        children: [{
                          ...ro,
                          path: '',
                          meta: {
                            ...ro.meta,
                            sidebar: false,
                            breadcrumb: false
                          }
                        }]
                      }
                })
              }
            : {
                ...rou,
                component: Layout,
                children: [{
                  ...rou
                }]
              }
        })
        // asyncRoutes.push(...frameworkRoutes)
        // 开启示例时， 注入示例路由
        if (import.meta.env.VITE_OPEN_EXAMPLE === 'true')
          fixasyncRoutes.push(..._asyncRoutes_ as any)

        const unallowedRoutes: Route.recordMainRaw[] = []
        // 如果权限功能开启，则需要对路由数据进行筛选过滤  -  前端路由权限判断（一般不需要前端做权限判断）
        // if (settingsStore.settings.app.enablePermission) {
        //   const permissions = await userStore.getPermissions()
        //   allowedRoutes = filterAsyncRoutes(asyncRoutes, permissions)
        //   unallowedRoutes = filterAsyncRoutesNoAuth(asyncRoutes, permissions)
        // }
        // else {
        const allowedRoutes = _.cloneDeep(fixasyncRoutes)
        // }
        routes.value = allowedRoutes.filter(item => item.children?.length !== 0) as any
        routesUnallowed.value = unallowedRoutes as any
        // 初始化常驻标签页
        if (settingsStore.settings.tabbar.enable)
          tabbarStore.initPermanentTab()

        systemMenuTree.value = ikTree.listToTree(res.data, { needSort: true })
        systemMenuList.value = res.data
        systemRouteMenu.value = routesMenu
        // 所有按钮
        const just_btn = await res.data.filter(
          (item: any) => item.menuType === MenuBtnEnum.PAGE_BUTTON
        ).map(({ menuType, name, permissionCode, parentId, remark, badge }: any) => {
          return {
            menuType, name, permissionCode, parentId, remark, badge
          }
        })
        ikStore.session.setItem(
          MenuStorageEnum.BUTTON,
          just_btn
        )
        ikStore.session.setItem(
          MenuStorageEnum.MENU,
          routesMenu
        )
        // 所有菜单、按钮
        ikStore.forage.setItem(MenuStorageEnum.ALL, res.data)
        // 所有菜单
        ikStore.forage.setItem(MenuStorageEnum.MENU, routesMenu)
        ElMessage.closeAll()
      }).catch(error => {
        console.info('error', error)
        ElMessage.closeAll()
      })
      // 用户授权
      userApi.setAuthGrant()
      // msgApi.getManagementList({
      //   businessKey: '',
      //   readStatus: 'NO_READ',
      //   receiverId: userStore.userInfo.id
      // }).then(resMsg => {
      // })
    }
    // 根据权限动态生成路由（文件系统生成）
    async function generateRoutesAtFilesystem(asyncRoutes: RouteRecordRaw[]) {
      let allowedRoutes
      let unallowedRoutes: RouteRecordRaw[] = []
      // 如果权限功能开启，则需要对路由数据进行筛选过滤
      if (settingsStore.settings.app.enablePermission) {
        const permissions = await userStore.getPermissions()
        allowedRoutes = filterAsyncRoutes(asyncRoutes, permissions)
        unallowedRoutes = filterAsyncRoutesNoAuth(asyncRoutes, permissions)
      }
      else {
        allowedRoutes = _.cloneDeep(asyncRoutes)
      }
      // 设置 routes 数据
      isGenerate.value = true
      fileSystemRoutes.value = allowedRoutes.filter(item => item.children?.length !== 0) as any
      routesUnallowed.value = unallowedRoutes as any
      // 加载常驻标签页
      if (settingsStore.settings.tabbar.enable)
        tabbarStore.initPermanentTab()
    }
    // 记录 accessRoutes 路由，用于登出时删除路由
    function setCurrentRemoveRoutes(routes: Function[]) {
      currentRemoveRoutes.value = routes
    }
    // 清空动态路由
    function removeRoutes() {
      isGenerate.value = false
      routes.value = []
      currentRemoveRoutes.value.forEach(removeRoute => {
        removeRoute()
      })
      currentRemoveRoutes.value = []
    }

    /**
     * 注册菜单到路由
     */
    function registerRoute() {
      // 注册并记录路由数据
      // 记录的数据会在登出时会使用到，不使用 router.removeRoute 是考虑配置的路由可能不一定有设置 name ，则通过调用 router.addRoute() 返回的回调进行删除
      const removeRoutes: Function[] = []
      // TODO 修改菜单渲染逻辑
      // routeStore.routes?.forEach(route => {
      //   if (!/^(https?:|mailto:|tel:)/.test(route.path))
      //     removeRoutes.push(router.addRoute(route as RouteRecordRaw))
      // })

      console.log('flatRoutes.value ', flatRoutes.value)
      flatRoutes.value?.forEach((route: any) => {
        if (!/^(https?:|mailto:|tel:)/.test(route.path)) {
          if (!router.hasRoute(route.name as RouteRecordName)) {
            if (route.component && !route.parentId) {
              //
              removeRoutes.push(router.addRoute({
                path: route.path,
                component: Layout,
                children: [route]
              }))
            }
            else {
              //
              removeRoutes.push(router.addRoute(route as RouteRecordRaw))
            }
          }
        }
      })
      if (settingsStore.settings.app.routeBaseOn !== 'filesystem') {
        flatSystemRoutes.value.forEach(route => {
          removeRoutes.push(router.addRoute(route as RouteRecordRaw))
        })
      }
      setCurrentRemoveRoutes(removeRoutes)
    }

    return {
      isGenerate,
      routes,
      fileSystemRoutes,
      currentRemoveRoutes,
      flatRoutes,
      flatRoutesUnallowed,
      flatSystemRoutes,
      systemMenuTree,
      systemMenuList,
      systemRouteMenu,
      generateRoutesAtFront,
      generateRoutesAtBack,
      generateRoutesAtFilesystem,
      setCurrentRemoveRoutes,
      removeRoutes,
      registerRoute
    }
  }
)

export default useRouteStore
